/**
 * 
 */
package com.vision.core.sv.serv.rpc;

import static com.vision.core.cm.data.AdminPermissions.CreateRole;
import static com.vision.core.cm.data.AdminPermissions.DeleteRole;
import static com.vision.core.cm.data.AdminPermissions.UpdateRole;
import static com.vision.core.cm.data.AdminPermissions.ViewRole;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vision.core.cm.data.Domain;
import com.vision.core.cm.db.data.Permission;
import com.vision.core.cm.db.data.Role;
import com.vision.core.cm.exception.DataNotFoundException;
import com.vision.core.cm.exception.RpcException;
import com.vision.core.cm.serv.rpc.RoleService;
import com.vision.core.sv.db.mgr.IDataManager;

/**
 * @author Mark
 *
 */
@Service("roles")
public class RoleServiceImpl extends AbstractServiceImpl<Role> implements RoleService {

	private static final long serialVersionUID = 1L;
	
	private static final Logger log = LoggerFactory.getLogger(RoleServiceImpl.class);

	public RoleServiceImpl() {
		initGilead();
	}

	@Autowired
	@Qualifier("roleManager")
	@Override
	public void setDataManager(IDataManager<Role> dataManager) {
		super.setDataManager(dataManager);
	}
	
	@Override
	public List<Role> getAll() throws RpcException {
		checkPermissions(ViewRole);
		
		return super.getAll();
	}
	
	@Transactional
	@Override
	public Role create(Role role) throws RpcException {
		checkPermissions(CreateRole);
		
		log.debug("Creating role: {}", role.getName());
		
		Role result = super.create(role);
		
		logCreate(result);
		
		return result;
	}
	
	@Transactional
	@Override
	public Role update(Role role) throws RpcException {
		checkPermissions(UpdateRole);
		Role existing = checkExisting(role);
		
		log.debug("Updating role: {}", role.getName());
		
		Role result = super.update(role);
		
		logUpdate(existing, result);
		
		return result;
	}
	
	@Transactional
	@Override
	public Role delete(Role role) throws RpcException {
		checkPermissions(DeleteRole);
		Role existing = checkExisting(role);
		
		log.debug("Deleting role: {}", existing.getName());
		
		Role result = super.delete(existing);
		
		logDelete(result);
		
		return result;
	}
	
	@Transactional
	@Override
	public List<Permission> assignPermissions(Role role, List<Permission> permissions) throws RpcException {
		checkPermissions(UpdateRole);
		Role existing = checkExisting(role);
		
		log.debug("Assigning permissions to role: {}", existing.getName());
		existing.addPermissions(permissions);
		
		super.update(existing);
		
		logAssociate(existing, permissions);
		
		return permissions;
	}
	
	@Transactional
	@Override
	public List<Permission> unassignPermissions(Role role, List<Permission> permissions) throws RpcException {
		checkPermissions(UpdateRole);
		Role existing = checkExisting(role);
		
		log.debug("Removing permissions from role: {}", existing.getName());
		existing.removePermissions(permissions);
		super.update(existing);
		
		logDeassociate(existing, permissions);
		
		return permissions;
	}
	
	@Override
	protected Domain getDomain() {
		return Domain.ROLE;
	}
	
	// Helpers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	protected Role checkExisting(Role param) throws DataNotFoundException {
		Role existingUser = getDataManager().getById(param.getName());
		if (existingUser == null)
			throw new DataNotFoundException("The Role does not exist.");
		return existingUser;
	}
	
}
